﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kelper.Domain.Data.Abstract;
using Kelper.Domain.Models;
using Kelper.Infrastructure;
using Kelper.Infrastructure.Abstract;
using Kelper.Infrastructure.Filters;

namespace Kelper.Controllers
{
    [ValidateInput(false)]
    public class RecipeController : BaseController
    {
        private IRecipeRepository recipes;
        private ICategoryRepository categories;    

        public RecipeController(IRecipeRepository recipeRepo, ICategoryRepository categoryRepo)
            : this(recipeRepo, categoryRepo, null) { }

        public RecipeController(IRecipeRepository recipeRepo, ICategoryRepository categoryRepo, IAccountManager accounts) 
            : base(accounts) 
        {
            recipes = recipeRepo;
            categories = categoryRepo;         
        }
            
        public ActionResult Index(int? id, string title)
        {
            Recipe result = recipes.Recipes.FirstOrDefault(r => r.ID == id);
            if (result != null)
            {
                if (result.UrlName() != (title ?? ""))
                    return RedirectToAction("index", new { id = id, title = result.UrlName() });

                LocalRecipeImageStore imageStore = GetImageStore();
                StoredFile file = imageStore.Get(result.ID);
                ViewBag.HasImage = file != null;

                return View(result);
            }

            return HttpNotFound();
        }

        [Login]
        public ViewResult Create()
        {
            SetupCategories();
            ViewBag.Action = "Create";
            return View(new Recipe());
        }

        [Login]
        [HttpPost]
        public ActionResult Create(Recipe recipe, IList<Ingredient> recipeIngredients,
            HttpPostedFileBase image, string type = "")
        {
            // These three rows make it a new recipe
            recipe.ID = 0;
            recipe.Author = new User { Username = accounts.CurrentUser };
            recipe.Created = DateTime.UtcNow;
            ViewBag.Action = "Create";

            if (SaveRecipe(recipe, recipeIngredients, image, type))
                return RedirectToAction("Index", "Home");
            return View(recipe);
        }

        [Login]
        public ActionResult Edit(int? id)
        {
            SetupCategories();
            string currentUser = accounts.CurrentUser;
            Recipe recipe = recipes.Recipes
                .FirstOrDefault(r => r.ID == id && r.Author.Username == currentUser);

            if (recipe != null)
            {
                SetupEdit(recipe);
                return View("Create", recipe);
            }
            else
                return RedirectToAction("Index", "user");
        }

        [Login]
        [HttpPost]
        public ActionResult Edit(Recipe recipe, IList<Ingredient> recipeIngredients,
            HttpPostedFileBase image, string button, string type = "")
        {
            string currentUser = accounts.CurrentUser;
            if (!recipes.Recipes.Any(r => r.ID == recipe.ID && r.Author.Username == currentUser))
                return RedirectToAction("Index", "Home");

            SetupCategories();
            ViewBag.Action = "Edit";

            SetupEdit(recipe);
            if (button == "Remove image")
                return View("create", recipe);

            recipe.Author = new User { Username = currentUser };
            if (SaveRecipe(recipe, recipeIngredients, image, type))
                return RedirectToAction("Index", new { id = recipe.ID, title = recipe.UrlName() });

            return View("create", recipe);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Remove(int id)
        {
            try
            {
                string currentUser = accounts.CurrentUser;
                Recipe result = recipes.Recipes
                    .First(r => r.Author.Username == currentUser && r.ID == id);

                GetImageStore().Remove(result.ID);

                recipes.Remove(id);
            }
            catch { }

            return RedirectToAction("Index", "user");
        }

        public FilePathResult Image(int id)
        {
            LocalRecipeImageStore imageStore = GetImageStore();
            StoredFile file = imageStore.Get(id);

            if (file != null)
                return File(file.FullName, file.ContentType);
            return null;
        }

        private bool SaveRecipe(Recipe recipe, IList<Ingredient> recipeIngredients,
            HttpPostedFileBase image, string type = "")
        {
            LocalRecipeImageStore imageStore = GetImageStore();
            SetupCategories();

            if (recipeIngredients.Count == 0)
                ModelState.AddModelError("", "There should be at least one ingredient");
            else if (image != null && !imageStore.IsValidFileExtension(image))
                ModelState.AddModelError("image", "Valid file types include jpg, png and bmp");

            recipe.Ingredients = recipeIngredients;
            if (ModelState.IsValid)
            {
                recipe.Category = new Category { Name = type };
                if (!recipes.Save(recipe))
                    ModelState.AddModelError("", "Failed to save recipe");
                else
                {
                    if (image != null)
                        imageStore.Save(recipe, image);
                    return true;
                }
            }

            ViewData["recipeIngredients"] = recipe.IngredientsCSV;
            return false;
        }

        private void SetupEdit(Recipe recipe)
        {
            ViewBag.Action = "Edit";
            ViewBag.HasImage = GetImageStore().Get(recipe.ID) != null;
            ViewData["recipeIngredients"] = recipe.IngredientsCSV;
        }

        private void SetupCategories()
        {
            ViewBag.Categories = categories.Categories.Select(c => c.Name);
        }

        private LocalRecipeImageStore GetImageStore()
        {
            return new LocalRecipeImageStore(Server.MapPath("~/Images"));
        }

       
    }
}
